class ScratchCurlExtension {
  // 1. 核心：定义扩展信息与积木（遵循官方 getInfo 规范）
  getInfo() {
    return {
      id: 'scratchCurl001', // 扩展唯一ID（建议自定义，避免重复）
      name: 'Curl网络请求', // 扩展名称（Scratch界面显示）
      blocks: [
        // 积木1：Curl GET 请求（命令型积木，带URL、请求头参数）
        {
          opcode: 'curlGet', // 积木唯一操作码（对应方法名）
          blockType: Scratch.BlockType.COMMAND,
          text: 'Curl GET 请求 | URL: [URL] | 请求头: [HEADERS]',
          arguments: {
            URL: {
              type: Scratch.ArgumentType.STRING,
              defaultValue: 'https://api.example.com/get' // 默认测试URL
            },
            HEADERS: {
              type: Scratch.ArgumentType.STRING,
              defaultValue: '{"Content-Type":"text/plain"}' // 默认请求头
            }
          }
        },
        // 积木2：Curl POST 请求（命令型积木，增加请求体参数）
        {
          opcode: 'curlPost',
          blockType: Scratch.BlockType.COMMAND,
          text: 'Curl POST 请求 | URL: [URL] | 头: [HEADERS] | 体: [BODY]',
          arguments: {
            URL: {
              type: Scratch.ArgumentType.STRING,
              defaultValue: 'https://api.example.com/post'
            },
            HEADERS: {
              type: Scratch.ArgumentType.STRING,
              defaultValue: '{"Content-Type":"application/json"}'
            },
            BODY: {
              type: Scratch.ArgumentType.STRING,
              defaultValue: '{"name":"scratch","value":"test"}' // 默认请求体
            }
          }
        },
        // 积木3：获取响应结果（报告型积木，返回请求数据）
        {
          opcode: 'getCurlResponse',
          blockType: Scratch.BlockType.REPORTER,
          text: 'Curl 响应结果'
        },
        // 积木4：获取响应状态码（报告型积木，返回HTTP状态码）
        {
          opcode: 'getCurlStatusCode',
          blockType: Scratch.BlockType.REPORTER,
          text: 'Curl 响应状态码'
        }
      ]
    };
  }

  // 2. 扩展状态存储（避免全局污染，仅内部访问）
  #responseData = '未发起请求'; // 响应结果（私有变量）
  #responseCode = 0; // 响应状态码（私有变量）

  // 3. 辅助方法：JSON解析（兼容用户输入错误）
  #parseJson(str) {
    try {
      return str.trim() ? JSON.parse(str) : {};
    } catch (e) {
      this.#responseData = '错误：请求头/请求体JSON格式无效';
      return {};
    }
  }

  // 4. 核心逻辑：Curl请求封装（GET/POST通用）
  async #curlRequest(method, url, headers = {}, body = {}) {
    try {
      // 初始化请求配置
      const options = {
        method: method.toUpperCase(),
        headers: new Headers(headers),
        mode: 'cors', // 适配Scratch跨域需求
        cache: 'no-cache'
      };

      // POST请求添加请求体
      if (method === 'POST' && Object.keys(body).length) {
        options.body = JSON.stringify(body);
      }

      // 发起请求
      const response = await fetch(url, options);
      this.#responseCode = response.status; // 更新状态码

      // 处理响应（支持文本/JSON）
      let resData = await response.text();
      try {
        resData = JSON.parse(resData); // 尝试解析JSON
      } catch (e) {}
      this.#responseData = resData;
    } catch (error) {
      this.#responseData = `错误：${error.message}`;
      this.#responseCode = 0;
    }
  }

  // 5. 积木对应方法：实现GET请求功能（opcode = curlGet）
  async curlGet(args) {
    const url = args.URL.trim();
    const headers = this.#parseJson(args.HEADERS);
    await this.#curlRequest('GET', url, headers);
  }

  // 6. 积木对应方法：实现POST请求功能（opcode = curlPost）
  async curlPost(args) {
    const url = args.URL.trim();
    const headers = this.#parseJson(args.HEADERS);
    const body = this.#parseJson(args.BODY);
    await this.#curlRequest('POST', url, headers, body);
  }

  // 7. 积木对应方法：返回响应结果（opcode = getCurlResponse）
  getCurlResponse() {
    return JSON.stringify(this.#responseData); // 转为字符串，适配Scratch处理
  }

  // 8. 积木对应方法：返回响应状态码（opcode = getCurlStatusCode）
  getCurlStatusCode() {
    return this.#responseCode.toString(); // 转为字符串，适配Scratch显示
  }
}

// 9. 官方规范：注册扩展（Scratch会自动识别）
Scratch.extensions.register(new ScratchCurlExtension());